package com.jun.rabbitmq.producer.controller;

import cn.hutool.core.util.IdUtil;
import com.jun.common.core.entity.constant.DateConstant;
import com.jun.common.core.entity.mq.RabbitMQRequestEntity;
import com.jun.common.core.entity.page.ResultHelper;
import com.jun.common.rabbitmq.constant.ExchangeConstant;
import com.jun.common.rabbitmq.constant.RouteConstant;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author yuejun.li
 * @date 2024/4/17 10:22:57
 */
@Api(tags = "消息发送接口")
@RestController
@RequestMapping("send")
@AllArgsConstructor
@Slf4j
public class SendController {

    private RabbitTemplate rabbitTemplate;

    @ApiOperation("发送消息")
    @GetMapping("email")
    public ResultHelper<String> email(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //将消息携带绑定键值：openKey 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TEST_DIRECT_EXCHANGE, RouteConstant.TEST_DIRECT_ROUTING_KEY, map);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息2")
    @GetMapping("email2")
    public ResultHelper<String> email2(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个主题邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //将消息携带绑定键值：topic.man 发送到交换机topicExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TOPIC_EXCHANGE, RouteConstant.TOPIC_MAN, map);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息3")
    @GetMapping("email3")
    public ResultHelper<String> email3(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "黄杏烨向你发了个主题邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //将消息携带绑定键值：topic.# 发送到交换机topicExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TOPIC_EXCHANGE, RouteConstant.TOPIC_WOMAN, map);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息4")
    @GetMapping("email4")
    public ResultHelper<String> email4(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "陈喜志向你发了个主题邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        //类似广播一样发送到交换机fanoutExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.FANOUT_EXCHANGE, null, map);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息5")
    @GetMapping("email5")
    public ResultHelper<String> email5(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        RabbitMQRequestEntity build = RabbitMQRequestEntity.builder()
                .businessId(IdUtil.simpleUUID())
                .data(map)
                .sendAppName("jun-admin")
                .sendTopic("测试")
                .build();
        //该id是用来追踪消息的唯一性。当消息无法路由到任何队列时，可以通过这个特性来处理消息。
        CorrelationData cd = new CorrelationData("lyj-"+ IdUtil.simpleUUID());
        /*cd.getFuture().addCallback(
                result -> {
                    // Future接收到回执的处理逻辑，参数中的result就是回执内容
                    if(result.isAck()){
                        // result.isAck()，boolean类型，true代表ack回执，false 代表 nack回执
                        log.info("发送消息成功，收到 ack!");
                        //生产者确认之后的业务逻辑
                    }else{
                        // result.getReason()，String类型，返回nack时的异常描述
                        log.error("发送消息失败，收到 nack, reason : {}", result.getReason());
                    }
                },
                ex -> {
                    // Future发生异常时的处理逻辑，基本不会触发
                    log.error("send message fail", ex);
                });*/

        //将消息携带绑定键值：openKey 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TEST_DIRECT_EXCHANGE, RouteConstant.TEST_DIRECT_ROUTING_KEY, build , cd);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息6")
    @GetMapping("email6")
    public ResultHelper<String> email6(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        RabbitMQRequestEntity build = RabbitMQRequestEntity.builder()
                .businessId(IdUtil.simpleUUID())
                .data(map)
                .sendAppName("jun-admin")
                .sendTopic("测试")
                .build();
        //该id是用来追踪消息的唯一性。当消息无法路由到任何队列时，可以通过这个特性来处理消息。
        CorrelationData cd = new CorrelationData("lyj-"+ IdUtil.simpleUUID());
        //将消息携带绑定键值：openKey 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TEST_DIRECT_EXCHANGE, RouteConstant.TEST_DIRECT_ROUTING_KEY, build , cd);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息7")
    @GetMapping("email7")
    public ResultHelper<String> email7(){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        RabbitMQRequestEntity build = RabbitMQRequestEntity.builder()
                .businessId(IdUtil.simpleUUID())
                .data(map)
                .sendAppName("jun-admin")
                .sendTopic("测试")
                .build();
        //该id是用来追踪消息的唯一性。当消息无法路由到任何队列时，可以通过这个特性来处理消息。
        CorrelationData cd = new CorrelationData("lyj-"+ IdUtil.simpleUUID());
        //设置消息信息
        MessagePostProcessor messagePostProcessor = processor -> {
            //单位毫秒
            processor.getMessageProperties().setExpiration("10000");
            return processor;
        };
        //将消息携带绑定键值：openKey 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.TEST_DIRECT_EXCHANGE_2, RouteConstant.TEST_DIRECT_ROUTING_KEY, build , messagePostProcessor,cd);
        return ResultHelper.success();
    }

    @ApiOperation("发送消息8")
    @GetMapping("email8")
    public ResultHelper<String> email8() {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(8, 15, 1L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(30), new ThreadPoolExecutor.CallerRunsPolicy());
        for (int i = 1; i <= 1000000; i++) {
            final int a = i;
            //该id是用来追踪消息的唯一性。当消息无法路由到任何队列时，可以通过这个特性来处理消息。
            CorrelationData cd = new CorrelationData("lyj-" + IdUtil.simpleUUID());
            RabbitMQRequestEntity build = RabbitMQRequestEntity.builder()
                    .businessId(IdUtil.simpleUUID())
                    .data("张三" + a)
                    .sendAppName("jun-admin")
                    .sendTopic("测试")
                    .build();
            threadPoolExecutor.execute(() -> {
                rabbitTemplate.convertAndSend(ExchangeConstant.TEST_DIRECT_EXCHANGE_3, RouteConstant.TEST_DIRECT_ROUTING_KEY, build, cd);
            });
        }
        return ResultHelper.success();
    }

    @ApiOperation("发送消息9")
    @GetMapping("email9")
    public ResultHelper<String> email9(Integer delayTime){
        String messageId = IdUtil.simpleUUID();
        String messageData = "李岳俊向你发了个邮件!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern(DateConstant.DATE_TIME_FORMAT));
        Map<String,Object> map=new HashMap<>();
        map.put("messageId",messageId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        RabbitMQRequestEntity build = RabbitMQRequestEntity.builder()
                .businessId(IdUtil.simpleUUID())
                .data(map)
                .sendAppName("jun-admin")
                .sendTopic("测试")
                .build();
        //该id是用来追踪消息的唯一性。当消息无法路由到任何队列时，可以通过这个特性来处理消息。
        CorrelationData cd = new CorrelationData("lyj-"+ IdUtil.simpleUUID());
        //设置消息信息
        MessagePostProcessor messagePostProcessor = processor -> {
            //单位毫秒
            processor.getMessageProperties().setDelay(delayTime);
            return processor;
        };
        //将消息携带绑定键值：openKey 发送到交换机TestDirectExchange
        rabbitTemplate.convertAndSend(ExchangeConstant.DELAY_EXCHANGE, RouteConstant.DELAY_KEY, build , messagePostProcessor,cd);
        return ResultHelper.success();
    }
}
